@@ -23,6 +23,10 @@ module AgentControllerConcern |
||
| 23 | 23 |
errors.add(:base, "#{target.name} cannot be scheduled")
|
| 24 | 24 |
end |
| 25 | 25 |
} |
| 26 |
+ when 'configure' |
|
| 27 |
+ if options['configure_options'].nil? || options['configure_options'].keys.length == 0 |
|
| 28 |
+ errors.add(:base, "The 'configure_options' options hash must be supplied when using the 'configure' action.") |
|
| 29 |
+ end |
|
| 26 | 30 |
when 'enable', 'disable' |
| 27 | 31 |
when nil |
| 28 | 32 |
errors.add(:base, "action must be specified") |
@@ -63,6 +67,9 @@ module AgentControllerConcern |
||
| 63 | 67 |
target.update!(disabled: true) |
| 64 | 68 |
log "Agent '#{target.name}' is disabled"
|
| 65 | 69 |
end |
| 70 |
+ when 'configure' |
|
| 71 |
+ target.update!(options: target.options.merge(interpolated['configure_options'])) |
|
| 72 |
+ log "Agent '#{target.name}' is configured with #{interpolated['configure_options'].inspect}"
|
|
| 66 | 73 |
when '' |
| 67 | 74 |
# Do nothing |
| 68 | 75 |
else |
@@ -5,7 +5,7 @@ module Agents |
||
| 5 | 5 |
cannot_create_events! |
| 6 | 6 |
|
| 7 | 7 |
description <<-MD |
| 8 |
- This agent is triggered by schedule or an incoming event and commands other agents ("targets") to run, disable or enable themselves.
|
|
| 8 |
+ This agent is triggered by schedule or an incoming event and commands other agents ("targets") to run, disable, configure, or enable themselves.
|
|
| 9 | 9 |
|
| 10 | 10 |
# Action types |
| 11 | 11 |
|
@@ -17,12 +17,16 @@ module Agents |
||
| 17 | 17 |
|
| 18 | 18 |
* `enable`: Target Agents are enabled (if not) when this agent is triggered. |
| 19 | 19 |
|
| 20 |
+ * `configure`: Target Agents have their options updated with the contents of `configure_options`. |
|
| 21 |
+ |
|
| 20 | 22 |
Here's a tip: you can use Liquid templating to dynamically determine the action type. For example: |
| 21 | 23 |
|
| 22 |
- - To create a CommanderAgent that receives an event from WeatherAgent every morning to kick an agent flow that is only useful in a nice weather, try this: `{% if conditions contains 'Sunny' or conditions contains 'Cloudy' %}run{% endif %}`
|
|
| 24 |
+ - To create a CommanderAgent that receives an event from a WeatherAgent every morning to kick an agent flow that is only useful in a nice weather, try this: `{% if conditions contains 'Sunny' or conditions contains 'Cloudy' %}run{% endif %}`
|
|
| 23 | 25 |
|
| 24 | 26 |
- Likewise, if you have a scheduled agent flow specially crafted for rainy days, try this: `{% if conditions contains 'Rain' %}enable{% else %}disabled{% endif %}`
|
| 25 | 27 |
|
| 28 |
+ - If you want to update a WeatherAgent based on a UserLocationAgent, you could use `'action': 'configure'` and set 'configure_options' to `{ 'location': '{{_location_.latlng}}' }`.
|
|
| 29 |
+ |
|
| 26 | 30 |
# Targets |
| 27 | 31 |
|
| 28 | 32 |
Select Agents that you want to control from this CommanderAgent. |
@@ -82,6 +82,10 @@ class Location |
||
| 82 | 82 |
!present? |
| 83 | 83 |
end |
| 84 | 84 |
|
| 85 |
+ def latlng |
|
| 86 |
+ "#{lat},#{lng}"
|
|
| 87 |
+ end |
|
| 88 |
+ |
|
| 85 | 89 |
private |
| 86 | 90 |
|
| 87 | 91 |
def floatify(value) |
@@ -100,7 +104,7 @@ class Location |
||
| 100 | 104 |
end |
| 101 | 105 |
|
| 102 | 106 |
class LocationDrop |
| 103 |
- KEYS = Location.members.map(&:to_s).concat(%w[latitude longitude]) |
|
| 107 |
+ KEYS = Location.members.map(&:to_s).concat(%w[latitude longitude latlng]) |
|
| 104 | 108 |
|
| 105 | 109 |
def before_method(key) |
| 106 | 110 |
if KEYS.include?(key) |
@@ -30,6 +30,10 @@ describe Location do |
||
| 30 | 30 |
expect(location['lat']).to eq 2.0 |
| 31 | 31 |
end |
| 32 | 32 |
|
| 33 |
+ it "has a convencience accessor for combined latitude and longitude" do |
|
| 34 |
+ expect(location.latlng).to eq "2.0,3.0" |
|
| 35 |
+ end |
|
| 36 |
+ |
|
| 33 | 37 |
it "does not allow hash-style assignment" do |
| 34 | 38 |
expect {
|
| 35 | 39 |
location[:lat] = 2.0 |
@@ -60,6 +64,7 @@ describe Location do |
||
| 60 | 64 |
'{{location.latitude}}' => '2.0',
|
| 61 | 65 |
'{{location.lng}}' => '3.0',
|
| 62 | 66 |
'{{location.longitude}}' => '3.0',
|
| 67 |
+ '{{location.latlng}}' => '2.0,3.0',
|
|
| 63 | 68 |
}.each { |template, result|
|
| 64 | 69 |
expect(Liquid::Template.parse(template).render('location' => location.to_liquid)).to eq(result),
|
| 65 | 70 |
"expected #{template.inspect} to expand to #{result.inspect}"
|
@@ -41,6 +41,15 @@ shared_examples_for AgentControllerConcern do |
||
| 41 | 41 |
expect(agent).to be_valid |
| 42 | 42 |
} |
| 43 | 43 |
end |
| 44 |
+ |
|
| 45 |
+ it "should ensure that 'configure_options' exists in options when the action is 'configure'" do |
|
| 46 |
+ agent.options['action'] = 'configure' |
|
| 47 |
+ expect(agent).not_to be_valid |
|
| 48 |
+ agent.options['configure_options'] = {}
|
|
| 49 |
+ expect(agent).not_to be_valid |
|
| 50 |
+ agent.options['configure_options'] = { 'key' => 'value' }
|
|
| 51 |
+ expect(agent).to be_valid |
|
| 52 |
+ end |
|
| 44 | 53 |
end |
| 45 | 54 |
end |
| 46 | 55 |
|
@@ -107,5 +116,17 @@ shared_examples_for AgentControllerConcern do |
||
| 107 | 116 |
agent.control! |
| 108 | 117 |
expect(agent.control_targets.reload).to all(satisfy { |a| !a.disabled? })
|
| 109 | 118 |
end |
| 119 |
+ |
|
| 120 |
+ it "should configure targets" do |
|
| 121 |
+ agent.options['action'] = 'configure' |
|
| 122 |
+ agent.options['configure_options'] = { 'url' => 'http://some-new-url.com/{{"something" | upcase}}' }
|
|
| 123 |
+ agent.save! |
|
| 124 |
+ old_options = agents(:bob_website_agent).options |
|
| 125 |
+ |
|
| 126 |
+ agent.control! |
|
| 127 |
+ |
|
| 128 |
+ expect(agent.control_targets.reload).to all(satisfy { |a| a.options['url'] == 'http://some-new-url.com/SOMETHING' })
|
|
| 129 |
+ expect(agents(:bob_website_agent).reload.options).to eq(old_options.merge('url' => 'http://some-new-url.com/SOMETHING'))
|
|
| 130 |
+ end |
|
| 110 | 131 |
end |
| 111 | 132 |
end |